package com.easylinkin.linkappapi.inspection.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.inspection.dto.ElectricBoxDTO;
import com.easylinkin.linkappapi.inspection.dto.ElectricCheckDTO;
import com.easylinkin.linkappapi.inspection.dto.ElectricOptionDTO;
import com.easylinkin.linkappapi.inspection.dto.ElectricStatisticsDTO;
import com.easylinkin.linkappapi.inspection.entity.ElectricBox;
import com.easylinkin.linkappapi.inspection.entity.ElectricCheck;
import com.easylinkin.linkappapi.inspection.entity.ElectricStatistics;
import com.easylinkin.linkappapi.inspection.mapper.ElectricBoxMapper;
import com.easylinkin.linkappapi.inspection.mapper.ElectricCheckMapper;
import com.easylinkin.linkappapi.inspection.mapper.ElectricStatisticsMapper;
import com.easylinkin.linkappapi.inspection.service.ElectricStatisticsService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 配电箱巡检统计表 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2022-04-13
 */
@Service
public class ElectricStatisticsServiceImpl extends ServiceImpl<ElectricStatisticsMapper, ElectricStatistics> implements
    ElectricStatisticsService {

  @Resource
  private LinkappUserContextProducer linkappUserContextProducer;

  @Autowired
  private ElectricBoxMapper electricBoxMapper;

  @Autowired
  private LinkappTenantMapper linkappTenantMapper;

  @Autowired
  private ElectricCheckMapper electricCheckMapper;

  /**
   * 增加
   * @param electricStatistics
   */
  @Override
  public void insert(ElectricStatistics electricStatistics) {
    /**
     * 验证重复
     */
    this.checkExist(electricStatistics);
    //设置基本属性
    this.setBase(electricStatistics);
    this.save(electricStatistics);
  }

  /**
   * 根据id编辑
   * @param electricStatistics
   */
  @Override
  public void updateOne(ElectricStatistics electricStatistics) {
    /**
     * 验证重复
     */
    this.checkExist(electricStatistics);
    //设置基本属性
    this.setBase(electricStatistics);
    this.updateById(electricStatistics);
  }

  /**
   * 更新今天的统计
   */
  @Override
  public void countToday() {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //计算当天的配电箱总数
    String sumIds = null;
    QueryWrapper<ElectricBox> boxWrapper = new QueryWrapper<>();
    boxWrapper.eq("tenant_id_",tenantId)
            .eq("use_state_",1)
        .eq("is_delete_",0);
    List<ElectricBox> electricBoxes = electricBoxMapper.selectList(boxWrapper);
    //所有的配电箱的code集合
    Set<String> ids = electricBoxes.stream().map(e -> e.getId()).collect(Collectors.toSet());
    if (ids.size() > 0){
      sumIds = StringUtils.join(ids, ",");
    }
    QueryWrapper<ElectricStatistics> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_",tenantId)
        .eq("record_time_", DateUtil.beginOfDay(new Date()));
    //查询库中有没有数据
    List<ElectricStatistics> statistics = baseMapper.selectList(queryWrapper);
    if (null != statistics && statistics.size() > 0){
      //更新
      ElectricStatistics electricStatistics = statistics.get(0);
      electricStatistics.setSum(ids.size());
      electricStatistics.setSumId(sumIds);
      this.setBase(electricStatistics);
      baseMapper.updateById(electricStatistics);
    }else {
      //新增
      ElectricStatistics electricStatistics = new ElectricStatistics();
      electricStatistics.setSum(ids.size());
      electricStatistics.setSumId(sumIds);
      this.setBase(electricStatistics);
      baseMapper.insert(electricStatistics);
    }
  }

  /**
   * @Description: 未巡检配电箱
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @Override
  public IPage<ElectricBox> undoList(RequestModel<ElectricStatisticsDTO> requestModel) {
    Page page = requestModel.getPage();
    ElectricStatisticsDTO electricStatisticsDTO = requestModel.getCustomQueryParams();
    String ids = electricStatisticsDTO.getSumId();
    String[] split = ids.split(",");
    List idList = new ArrayList(Arrays.asList(split));
    Integer done = electricStatisticsDTO.getDone();
    if (done > 0){
      //查询已经巡检的
      QueryWrapper<ElectricCheck> queryWrapper = new QueryWrapper<>();
      queryWrapper.ge("check_time_",DateUtil.beginOfDay(electricStatisticsDTO.getRecordTime()))
          .le("check_time_",DateUtil.endOfDay(electricStatisticsDTO.getRecordTime()))
          .eq("tenant_id_",linkappUserContextProducer.getNotNullCurrent().getTenantId());
      List<ElectricCheck> checks = electricCheckMapper.selectList(queryWrapper);
      if (null != checks && checks.size() > 0){
        //删除已巡检的
        Set<String> idSet = checks.stream().map(c -> c.getElectricBoxId()).collect(Collectors.toSet());
        idList = (List) idList.stream().filter(id -> !idSet.contains(id)).collect(Collectors.toList());
      }
    }
    ElectricBox electricBox = new ElectricBox();
    electricBox.setTenantId(electricStatisticsDTO.getTenantId());
    electricBox.setIds(new HashSet<>(idList));
    IPage<ElectricBox> electricBoxIPage = electricBoxMapper.queryListByPage(page, electricBox);
    return electricBoxIPage;
  }

  /**
   * @Description: 已巡检配电箱
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @Override
  public IPage<ElectricBox> done(RequestModel<ElectricStatisticsDTO> requestModel) {
    Page page = requestModel.getPage();
    ElectricStatisticsDTO electricStatisticsDTO = requestModel.getCustomQueryParams();
    //查询已经巡检的
    ElectricBoxDTO electricBoxDTO = new ElectricBoxDTO();
    electricBoxDTO.setStartTime(DateUtil.beginOfDay(electricStatisticsDTO.getRecordTime()));
    electricBoxDTO.setEndTime(DateUtil.endOfDay(electricStatisticsDTO.getRecordTime()));
    electricBoxDTO.setTenantId(electricStatisticsDTO.getTenantId());
    IPage<ElectricBox> electricBoxIPage = electricBoxMapper.getDone(page, electricBoxDTO);
    return electricBoxIPage;
  }

  @Override
  public IPage<ElectricStatisticsDTO> queryListByPage(RequestModel<ElectricStatisticsDTO> requestModel) {
    Page page = requestModel.getPage();
    ElectricStatisticsDTO electricStatisticsDTO = requestModel.getCustomQueryParams();
    //项目id 过滤
    electricStatisticsDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    Integer type = electricStatisticsDTO.getType();
    //查询条件处理
    if (Integer.valueOf(1).equals(type)){
      electricStatisticsDTO.setStartTime(DateUtil.beginOfWeek(new Date()));
      electricStatisticsDTO.setEndTime(DateUtil.endOfWeek(new Date()));
    }else if (Integer.valueOf(2).equals(type)){
      electricStatisticsDTO.setStartTime(DateUtil.beginOfMonth(new Date()));
      electricStatisticsDTO.setEndTime(DateUtil.endOfMonth(new Date()));
    }else {
      Calendar c = Calendar.getInstance();
      c.setTime(new Date());
      c.add(Calendar.MONTH, -3);
      electricStatisticsDTO.setStartTime(DateUtil.beginOfDay(c.getTime()));
      electricStatisticsDTO.setEndTime(DateUtil.endOfDay(new Date()));
    }
    IPage<ElectricStatisticsDTO> electricStatisticsIPage = baseMapper.queryListByPage(page, electricStatisticsDTO);
    //处理异常数据
    filterErrorInfo(electricStatisticsIPage.getRecords());
    return electricStatisticsIPage;
  }

  private void filterErrorInfo(List<ElectricStatisticsDTO> records) {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    records.forEach(electricStatistics -> {
      Date startTime = electricStatistics.getRecordTime();
      Calendar instance = Calendar.getInstance();
      instance.setTime(startTime);
      Date endTime = DateUtil.endOfDay(instance).getTime();
      QueryWrapper<ElectricCheck> wrapper = new QueryWrapper();
      wrapper.between("check_time_", startTime, endTime);
      wrapper.eq("tenant_id_", tenantId);
      List<ElectricCheck> checkList = electricCheckMapper.selectList(wrapper);
      if(CollectionUtil.isNotEmpty(checkList)){
        List<ElectricCheck> error = checkList.stream().filter(item -> {
          String content = item.getContent();
          List<JSONObject> list = JSONObject.parseObject(content, List.class);
          long count = list.stream().filter(o -> {
            return Integer.valueOf("0").equals(o.getInteger("value"));
          }).count();
          return count > 0;
        }).collect(Collectors.toList());
        electricStatistics.setErrorNum(error.size());
      }else {
        electricStatistics.setErrorNum(0);
      }
    });
  }

  /**
   * 统计当天的配电箱
   */
  @Scheduled(cron = "0 5 3 * * ?")
  public void checkCount(){
    try {
      log.error("统计当天配电箱定时任务checkCount--------开始-----start--------");
      //查询所有项目
      List<LinkappTenant> list = linkappTenantMapper.selectByProjectId(null);
      list.removeIf(l -> "1".equals(l.getId()));
      list.forEach(l -> {
        //计算当天的配电箱总数
        countToday(l.getId(),0);
      });
      log.error("统计当天配电箱定时任务checkCount--------结束-----end--------");
    }catch (Exception e){
      log.error("统计当天配电箱定时任务checkCount--------异常-----error--------",e);
    }
  }

  @Override
  public void countToday(String tenantId,Integer done) {
    String sumIds = null;
    QueryWrapper<ElectricBox> boxWrapper = new QueryWrapper<>();
    boxWrapper.eq("tenant_id_",tenantId)
            .eq("use_state_",1)
        .eq("is_delete_",0);
    List<ElectricBox> electricBoxes = electricBoxMapper.selectList(boxWrapper);
    //所有的配电箱的code集合
    Set<String> ids = electricBoxes.stream().map(e -> e.getId()).collect(Collectors.toSet());
    if (ids.size() > 0){
      sumIds = StringUtils.join(ids, ",");
    }
    //新增
    ElectricStatistics electricStatistics = new ElectricStatistics();
    electricStatistics.setSum(ids.size());
    electricStatistics.setSumId(sumIds);
    electricStatistics.setDone(null==done?0:done);
    electricStatistics.setTenantId(tenantId);
    this.setBase(electricStatistics);
    baseMapper.insert(electricStatistics);
  }

  /**
   * 验证重复
   */
  private void checkExist(ElectricStatistics electricStatistics) {
    QueryWrapper<ElectricStatistics> queryWrapper = new QueryWrapper<>();
    //todo 设置判断重复条件
    //编辑的时候存在id
    Optional.ofNullable(electricStatistics.getId()).ifPresent(id -> queryWrapper.ne("id",electricStatistics.getId()));
    Integer integer = baseMapper.selectCount(queryWrapper);
    if (integer>0){
      throw new BusinessException("该配电箱巡检统计已存在");
    }
  }

  /**
   * 设置基本属性
   * @param electricStatistics
   */
  private void setBase(ElectricStatistics electricStatistics) {
    electricStatistics.setModifyTime(new Date());
    if (null != linkappUserContextProducer.getCurrent()){
      electricStatistics.setModifyId(linkappUserContextProducer.getCurrent().getId());
    }
    //没有id就是新增,有就是编辑
    if (StringUtils.isBlank(electricStatistics.getId())){
      electricStatistics.setRecordTime(DateUtil.beginOfDay(new Date()));
      if (null != linkappUserContextProducer.getCurrent()){
        electricStatistics.setCreatorId(linkappUserContextProducer.getCurrent().getId());
      }
      electricStatistics.setCreateTime(new Date());
      if (StringUtils.isBlank(electricStatistics.getTenantId())){
        electricStatistics.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
      }
    }
  }
}
